package com.ethank.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ethank.common.core.domain.AjaxResult;
import com.ethank.common.utils.StringUtils;
import com.ethank.common.utils.uuid.UUID;
import com.ethank.constant.WxConstant;
import com.ethank.mapper.FnaInvoiceLedgerMapper;
import com.ethank.service.WxService;
import com.ethank.utils.HttpClientUtil;
import org.apache.tomcat.util.bcel.Const;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author tf
 * @date 2024-02-28
 * @Description
 */

@Service
public class WxServiceImpl implements WxService {

    @Value("${wx.corpId}")
    private String corpId;

    @Value("${wx.corpSecret}")
    private String corpSecret;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    FnaInvoiceLedgerMapper fnaInvoiceLedgerMapper;


    private static final Logger logger = LoggerFactory.getLogger(WxServiceImpl.class);
    private static final String ACCESS_TOKEN_KEY = "ethank::ocr::wx::access::";
    private static final String TICKET_KEY = "ethank::ocr::wx::ticket::";

    /**
     * @Description: JsApi签名
     * @Param: [url]
     * @return: com.ethank.common.core.domain.AjaxResult
     * @Author: tf
     * @Date: 2024-02-28
     */

    @Override
    public AjaxResult getJsSign(String url, String clientId) throws Exception {
        if (StringUtils.isBlank(url)) {
            return AjaxResult.error("请求参数不可为空");
        }
        // 查询是否存在有效的tikcet
        String ticket = "";
        // 1. 获取access_token
        String accessToken = getAccessToken();
        if (StringUtils.isBlank(accessToken)) {
            return AjaxResult.error("获取ACCESS-TOKEN失败");
        }
        // 2. 获取ticket
        ticket = getTicket(accessToken);
        if (StringUtils.isBlank(ticket)) {
            return AjaxResult.error("获取JSAPI-TICKET失败");
        }
        // 3.生成相应签名
        String timestamp = Long.toString(System.currentTimeMillis()).substring(0, 10);
        ;
        String nonce = getRandomString(16);
        String sign = getSign(url, timestamp, nonce, ticket);
        HashMap<String, Object> resultMap = new HashMap<>(4);
        resultMap.put("timestamp", timestamp);
        resultMap.put("nonceStr", nonce);
        resultMap.put("signature", sign);
        resultMap.put("appId", corpId);
        return AjaxResult.success(resultMap);
    }



    private String getSign(String url, String timestamp, String nonce, String ticket) throws Exception {
        String templateStr = "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s";
        String templateData = String.format(templateStr, ticket, nonce, timestamp, url);
        logger.info("getSign=>templateData=>" + templateData);
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        md.reset();
        md.update(templateData.getBytes("UTF-8"));
        byte[] hashBytes = md.digest();
        // 将散列值转换为十六进制字符串表示
        StringBuilder hexString = new StringBuilder();
        for (byte b : hashBytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }

        System.out.println("SHA-1 Hash: " + hexString.toString());


        return hexString.toString();
    }

    /**
     * @Description: 获取access_token
     * @Param: []
     * @return: java.lang.String
     * @Author: tf
     * @Date: 2024-02-28
     */
    public String getAccessToken() {
        //检测是否存在有效的access_token
        Object redisToken = stringRedisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
        logger.info("redis=>getAccessToken=>"+String.valueOf(redisToken));
        if (null != redisToken) {
            return String.valueOf(redisToken);
        }
        String url = String.format(WxConstant.ACCESS_TOKEN_URL, corpId, corpSecret);
        String resToken = HttpClientUtil.get(url);
        JSONObject jsonObject = JSON.parseObject(resToken);
        if (!jsonObject.getInteger("errcode").equals(0)) {
            return "";
        }
        logger.info("getAccessToken=>resToken=>" + resToken);
        String token = jsonObject.getString("access_token");
        //缓存access_token
        stringRedisTemplate.opsForValue().set(ACCESS_TOKEN_KEY, token, 7100, TimeUnit.SECONDS);
        return token;
    }

    /**
     * @Description:
     * @Param: [accessToken]
     * @return: java.lang.String
     * @Author: tf
     * @Date: 2024-02-28
     */
    public String getTicket(String accessToken) {
        //检测是否存在有效的凭证
        Object redisToken = stringRedisTemplate.opsForValue().get(TICKET_KEY);
        logger.info("redis=>getTicket=>"+String.valueOf(redisToken));

        if (null != redisToken) {
            return String.valueOf(redisToken);
        }
        String url = String.format(WxConstant.TICKET_URL, accessToken);
        String ticketData = HttpClientUtil.get(url);
        JSONObject jsonObject = JSONObject.parseObject(ticketData);
        if (!jsonObject.getInteger("errcode").equals(0)) {
            return "";
        }
        String ticket = jsonObject.getString("ticket");
        logger.info("getTicket=>ticket=>" + ticketData);
        stringRedisTemplate.opsForValue().set(TICKET_KEY, ticket, 7100, TimeUnit.SECONDS);
        return ticket;
    }

    private static String getRandomString(int length) {
        String keyString = "ergrfewfwdgggcvv;uihefujsncjdvngrjegeuirgverggvbergbvuigverug";
        int len = keyString.length();
        StringBuffer str = new StringBuffer();
        for (int i = 0; i < length; i++) {
            str.append(keyString.charAt((int) Math.round(Math.random() * (len - 1))));
        }
        return str.toString();
    }
    @Override
    public AjaxResult getUserInfo(String code) {
        if(StringUtils.isBlank(code)){
            return AjaxResult.error("code不可为空");
        }
        String accessToken = getAccessToken();
        String url = String.format(WxConstant.USER_INFO_URL, accessToken, code);
        String resToken = HttpClientUtil.get(url);
        JSONObject jsonObject = JSON.parseObject(resToken);
        logger.info("INFO=>getUserInfo"+jsonObject.toString());
        if(!jsonObject.getInteger("errcode").equals(0)){
            return AjaxResult.error("获取用户信息有误");
        }
        String wechatUserId = jsonObject.getString("UserId");
        //OA的和企微不一致 进行转换处理
        if("666661809".equals(jsonObject.getString("UserId"))){
            wechatUserId =  "010310";
        }
        //工号转换成员工ID
        Integer userId = fnaInvoiceLedgerMapper.getUserId(wechatUserId);
        if(null == userId){
            return AjaxResult.error("查询员工ID异常");
        }
        jsonObject.put("UserId",String.valueOf(userId));
        return AjaxResult.success(jsonObject);
    }

}
